package query_service

import (
	"github.com/gin-gonic/gin"
	"go.uber.org/zap"
	"mine-info-server/app/convertor"
	"mine-info-server/domain/plan-manage-context/model/plan-aggregate/aggregate"
	entity2 "mine-info-server/domain/plan-manage-context/model/plan-aggregate/entity"
	"mine-info-server/domain/plan-manage-context/query"
	"mine-info-server/domain/plan-manage-context/repo"
	"mine-info-server/global"
	"mine-info-server/interfaces/response"
	"mine-info-server/utils"
	"mine-info-server/utils/consts"
	"sync"
)

/*
   @author：zhongyang
   @date:2023/4/2
   @description: 计划管理-查询应用服务（查询）
*/

type PlanManageQueryService struct {
	PlanManageRepo repo.PlanManageIRepo
	planConvertor  convertor.PlanManageConvertor
}

func (s *PlanManageQueryService) GeneratePlanReport(context *gin.Context, query *query.GeneratePlanReportQuery) (interface{}, error) {
	// 拿到完整的计划聚合根
	plan, err := s.PlanManageRepo.FindCompletePlanById(context, query.PlanId)
	if err != nil {
		return nil, err
	}
	// 在聚合根里面生成报告，并返回。
	err = plan.GenerateReport()
	if err != nil {
		return nil, err
	}
	// 转换回DTO，并返回
	return s.planConvertor.ConvertPlanReportResponse(plan), nil
}

func (s *PlanManageQueryService) FindPlan(context *gin.Context, query *query.GetPlanQuery) (*response.PlanResponse, error) {
	plan, err := s.PlanManageRepo.FindPlanById(context, query.PlanId)
	if err != nil {
		return nil, err
	}
	// 将聚合根转换成DTO并返回
	return s.planConvertor.ConvertPlanResponse(plan), nil
}

func (s *PlanManageQueryService) FindPlanDetail(context *gin.Context, detailQuery *query.GetPlanDetailQuery) (*response.PlanDetailResponse, error) {
	plan, err := s.PlanManageRepo.FindPlanContainsDetailById(context, detailQuery.PlanId)
	if err != nil {
		return nil, err
	}
	return s.planConvertor.ConvertPlanDetailResponse(plan), nil
}

func (s *PlanManageQueryService) FindPlanMultiLevelList(context *gin.Context, listQuery *query.GetPlanListQuery) ([]*response.PlanPageResponse, int64, error) {
	parentPlans, total, err := s.PlanManageRepo.FindParentPlanListPage(context, listQuery.Page, listQuery.PageSize, utils.GetUserID(context))
	if err != nil {
		return nil, 0, err
	}
	var wg sync.WaitGroup
	for _, planAgr := range parentPlans {
		wg.Add(1)
		go func(item *aggregate.PlanAggregate) {
			defer wg.Done()
			todoTotal, err := s.PlanManageRepo.GetTaskTotalByPlanId(item.PlanId, consts.FinishedBool)
			if err != nil {
				global.GVA_LOG.Error("查询total异常 err:%v", zap.Error(err))
			}
			item.CalTaskTotal(todoTotal)
			childrenPlan, err := s.getChildrenPlan(item.PlanId, utils.GetUserID(context))
			if err != nil {
				global.GVA_LOG.Error("查询childrenRes异常 err:%v", zap.Error(err))
			}
			item.AddChildrenPlan(childrenPlan)
		}(planAgr)
		planAgr.CalPlanStatus()
		planAgr.CalSurplusTime()
	}
	wg.Wait()
	res := s.planConvertor.ConvertPlanPageResponse(parentPlans)
	return res, total, nil
}

func (s *PlanManageQueryService) FindPlanReport(context *gin.Context, reportQuery *query.FindPlanReportQuery) (*response.PlanReportResponse, error) {
	plan, err := s.PlanManageRepo.FindPlanContainsReportById(context, reportQuery.PlanId)
	if err != nil {
		return nil, err
	}
	return s.planConvertor.ConvertPlanReportResponse(plan), err
}

func (s *PlanManageQueryService) getChildrenPlan(parentId, userID string) ([]*aggregate.PlanAggregate, error) {
	var wg sync.WaitGroup
	children, err := s.PlanManageRepo.FindChildrenPlanListByParentId(parentId, userID)
	if err != nil {
		return nil, err
	}
	for _, child := range children {
		wg.Add(1)
		go func(plan *aggregate.PlanAggregate) {
			defer wg.Done()
			total, err := s.PlanManageRepo.GetTaskTotalByPlanId(plan.PlanId, consts.FinishedBool)
			if err != nil {
				global.GVA_LOG.Error("查询total异常 err:%v", zap.Error(err))
				return
			}
			plan.CalTaskTotal(total)
		}(child)
		child.CalPlanStatus()
		child.CalSurplusTime()
	}
	wg.Wait()
	return children, nil
}

func (s *PlanManageQueryService) GetTaskItemById(context *gin.Context, itemQuery *query.GetTaskItemQuery) (*response.TaskItemResponse, error) {
	plan, err := s.PlanManageRepo.GetTaskItemById(context, itemQuery.TaskItemId)
	if err != nil {
		return nil, err
	}
	return s.planConvertor.ConvertTaskItem(plan), nil
}

func (s *PlanManageQueryService) GetTaskList(context *gin.Context, listQuery *query.GetTaskListQuery) ([]*response.TaskListResponse, int64, error) {
	plan, total, err := s.PlanManageRepo.GetTaskList(context, listQuery.PlanId, listQuery.Page, listQuery.PageSize)
	if err != nil {
		return nil, 0, err
	}
	return s.planConvertor.ConvertTaskList(plan), total, nil
}

func (s *PlanManageQueryService) FindOneDayQuestions(context *gin.Context, questionQuery *query.FindOneDayQuestionQuery) ([]*response.QuestionResponse, error) {
	plan, err := s.PlanManageRepo.FindOneDayQuestions(context, questionQuery.PlanId, questionQuery.TaskDate)
	if err != nil {
		return nil, err
	}
	return s.planConvertor.ConvertQuestions(plan), nil
}

func (s *PlanManageQueryService) SearchQuestions(context *gin.Context, questionQuery *query.SearchQuestionQuery) ([]*response.QuestionResponse, error) {
	plan, err := s.PlanManageRepo.SearchQuestions(context, questionQuery.PlanId, questionQuery.Content)
	if err != nil {
		return nil, err
	}
	return s.planConvertor.ConvertQuestions(plan), nil
}

// todo 这里代码放到repo去
func (s *PlanManageQueryService) GetOngoingTasks(context *gin.Context, tasksQuery *query.GetOngoingTasksQuery) ([]*response.TaskItemResponse, error) {
	// 获取进行中的计划
	planIds, err := s.PlanManageRepo.FindOngoingPlanIds(utils.GetUserID(context))
	if err != nil {
		return nil, err
	}
	// 获取对应待办
	tasks, err := s.PlanManageRepo.GetOngoingTasksByPlanIds(context, planIds, tasksQuery.Scope)
	var res []*response.TaskItemResponse
	var wg sync.WaitGroup
	var mu sync.Mutex
	// 再获取所有待办项
	for _, task := range tasks {
		wg.Add(1)
		go func(taskReq *entity2.Task) {
			defer wg.Done()
			taskItems, err := s.PlanManageRepo.FindOngoingTaskItems(taskReq.TaskId)
			if err != nil {
				return
			}
			mu.Lock()
			for _, item := range taskItems {
				itemRes := &response.TaskItemResponse{
					TodoItemId: item.Id,
					Content:    item.Content,
					TodoId:     taskReq.TaskId,
					Level:      item.Level,
					PlanId:     taskReq.PlanId,
					FinishDate: item.FinishDate,
				}
				res = append(res, itemRes)
			}
			mu.Unlock()
		}(task)
	}
	wg.Wait()
	return res, nil
}

func (s *PlanManageQueryService) IsFinishTask(context *gin.Context, taskQuery *query.IsFinishTaskQuery) (bool, error) {
	return s.PlanManageRepo.IsFinishTask(context, taskQuery.PlanID)
}

func (s *PlanManageQueryService) GetAllPlan(context *gin.Context, userID string) ([]*response.PlanResponse, error) {
	// 根据用户id查询所有计划
	plans, err := s.PlanManageRepo.FindAllPlanByUserId(userID)
	if err != nil {
		return nil, err
	}
	var res []*response.PlanResponse
	for _, plan := range plans {
		res = append(res, s.planConvertor.ConvertPlanResponse(plan))
	}
	return res, nil
}
